/*
 * Copyright 2012 Roman Nurik
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jy.appmarket.widget;

import java.util.ArrayList;
import java.util.List;

import com.jy.appmarket.R;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.widget.CompoundButton;

/**
 * A two-state button that indicates whether some related content is pinned (the
 * checked state) or unpinned (the unchecked state), and the download progress
 * for this content.
 * <p>
 * See <a href=
 * "http://developer.android.com/design/building-blocks/progress.html#custom-indicators">Android
 * Design: Progress &amp; Activity</a> for more details on this custom
 * indicator.
 */
public class PinProgressButton extends CompoundButton {

	private int mMax;
	private int mProgress;

	private Paint mCirclePaint;
	private Paint mProgressPaint;
	private Paint mPaintWhite;
	private Paint mPaint;
	private RectF mTempRectF = new RectF();
	private RectF mStateRectF = new RectF();

	private int mViewWidth;
	private int mViewHeight;
	private Bitmap mShadowBitmap;

	private DownloadState mDownloadState = DownloadState.DEFAULT;

	public DownloadState getDownloadState() {
		return mDownloadState;
	}

	public void setDownloadState(DownloadState mDownloadState) {
		this.mDownloadState = mDownloadState;
	}

	private List<Bitmap> mStateBitmaps = new ArrayList<Bitmap>();

	public enum DownloadState {
		DEFAULT, DOWNLOAD_WAITING, DOWNLOAD_PAUSE, DOWNLOAD_ERROR
	}

	public PinProgressButton(Context context) {
		super(context);
		init(context, null, 0);
	}

	public PinProgressButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context, attrs, 0);
	}

	public PinProgressButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context, attrs, defStyle);
	}

	private void init(Context context, AttributeSet attrs, int defStyle) {
		mMax = 100;
		mProgress = 0;

		final Resources res = getResources();
		int circleColor = res.getColor(R.color.pin_progress_default_circle_color);
		int progressColor = res.getColor(R.color.pin_progress_default_progress_color);

		mViewHeight = (int) getResources().getDimension(R.dimen.pin_progress_button_height) + 1;
		mViewWidth = (int) getResources().getDimension(R.dimen.pin_progress_button_width) + 1;

		if (attrs != null) {
			// Attribute initialization
			final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PinProgressButton, defStyle, 0);

			mMax = a.getInteger(R.styleable.PinProgressButton_progressMax, mMax);
			mProgress = a.getInteger(R.styleable.PinProgressButton_progress, mProgress);

			circleColor = a.getColor(R.styleable.PinProgressButton_circleColor, circleColor);
			progressColor = a.getColor(R.styleable.PinProgressButton_progressColor, progressColor);

			mViewWidth = (int) a.getDimension(R.styleable.PinProgressButton_layout_width, mViewHeight) + 1;
			mViewHeight = (int) a.getDimension(R.styleable.PinProgressButton_layout_height, mViewWidth) + 1;

			a.recycle();
		}

		mCirclePaint = new Paint();
		mCirclePaint.setColor(circleColor);
		mCirclePaint.setAntiAlias(true);

		mProgressPaint = new Paint();
		mProgressPaint.setColor(progressColor);
		mProgressPaint.setAntiAlias(true);

		mPaintWhite = new Paint();
		mPaintWhite.setAntiAlias(true);
		mPaintWhite.setColor(Color.parseColor("#FFFFFF"));
		mPaintWhite.setStrokeWidth(3);
		mPaintWhite.setStyle(Style.STROKE);

		mPaint = new Paint();
		mPaint.setFilterBitmap(false);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setShader(null);

		mStateBitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.download_waiting));
		mStateBitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.download_pause));
		mStateBitmaps.add(BitmapFactory.decodeResource(context.getResources(), R.drawable.download_error));

		mShadowBitmap = Bitmap.createScaledBitmap(
				BitmapFactory.decodeResource(context.getResources(), R.drawable.pinprogress_background), mViewWidth,
				mViewHeight, false);

		mTempRectF.set(mViewWidth * 0.2f - 0.5f, mViewHeight * 0.2f - 0.5f, mViewWidth * 0.8f + 0.5f,
				mViewHeight * 0.8f + 0.5f);

		Drawable drawable = getResources().getDrawable(R.drawable.download_waiting);
		mStateRectF.set((mViewWidth - drawable.getIntrinsicWidth()) / 2,
				(mViewHeight - drawable.getIntrinsicHeight()) / 2,
				(mViewWidth - drawable.getIntrinsicWidth()) / 2 + drawable.getIntrinsicWidth(),
				(mViewHeight - drawable.getIntrinsicHeight()) / 2 + drawable.getIntrinsicHeight());
	}

	/**
	 * Returns the maximum download progress value.
	 */
	public synchronized int getMax() {
		return mMax;
	}

	/**
	 * Sets the maximum download progress value. Defaults to 100.
	 */
	public synchronized void setMax(int max) {
		if (max < 0) {
			throw new IllegalArgumentException("max not less than 0");
		}
		mMax = max;
		postInvalidate();
	}

	/**
	 * Returns the current download progress from 0 to max.
	 */
	public synchronized int getProgress() {
		return mProgress;
	}

	/**
	 * Sets the current download progress (between 0 and max).
	 * 
	 * @see #setMax(int)
	 */
	public synchronized void setProgress(int progress) {
		if (progress < 0) {
			throw new IllegalArgumentException("progress not less than 0");
		}
		if (progress > mMax) {
			progress = mMax;
		}
		if (progress <= mMax) {
			mProgress = progress;
			postInvalidate();
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		setMeasuredDimension(resolveSize(mViewWidth, widthMeasureSpec), resolveSize(mViewHeight, heightMeasureSpec));
	}

	private PorterDuffXfermode mXferMode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		canvas.saveLayer(0, 0, mViewWidth, mViewHeight, null,
				Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
						| Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);

		// 合并bitmap
		canvas.drawBitmap(mShadowBitmap, 0, 0, null);
		mPaint.setXfermode(mXferMode);
		canvas.drawBitmap(createBitmap(200, 200), 0, 0, mPaint);
		mPaint.setXfermode(null);

		// 画圈
		canvas.drawArc(mTempRectF, -90, 360, false, mPaintWhite);

		// 画下载状态，为Default不需要画
		int stateBitmapIndex = 0;
		if (mDownloadState != DownloadState.DEFAULT) {
			if (mDownloadState == DownloadState.DOWNLOAD_WAITING) {
				stateBitmapIndex = 0;
			} else if (mDownloadState == DownloadState.DOWNLOAD_PAUSE) {
				stateBitmapIndex = 1;
			} else if (mDownloadState == DownloadState.DOWNLOAD_ERROR) {
				stateBitmapIndex = 2;
			}
			canvas.drawBitmap(mStateBitmaps.get(stateBitmapIndex), null, mStateRectF, null);
		}
	}

	// create a bitmap with a circle
	private Bitmap createBitmap(int w, int h) {
		Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
		Canvas c = new Canvas(bm);

		// 画圆
		c.drawArc(mTempRectF, -90 + 360 * mProgress / mMax, 360 * (mMax - mProgress) / mMax, true, mCirclePaint);
		c.drawArc(mTempRectF, -90, 360 * mProgress / mMax, true, mProgressPaint);
		return bm;
	}

	/**
	 * A {@link Parcelable} representing the {@link PinProgressButton}'s state.
	 */
	public static class SavedState extends BaseSavedState {
		private int mProgress;
		private int mMax;

		public SavedState(Parcelable superState) {
			super(superState);
		}

		private SavedState(Parcel in) {
			super(in);
			mProgress = in.readInt();
			mMax = in.readInt();
		}

		@Override
		public void writeToParcel(Parcel out, int flags) {
			super.writeToParcel(out, flags);
			out.writeInt(mProgress);
			out.writeInt(mMax);
		}

		public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
			@Override
			public SavedState createFromParcel(Parcel parcel) {
				return new SavedState(parcel);
			}

			@Override
			public SavedState[] newArray(int size) {
				return new SavedState[size];
			}
		};

	}

	@Override
	public Parcelable onSaveInstanceState() {
		Parcelable superState = super.onSaveInstanceState();
		if (isSaveEnabled()) {
			SavedState ss = new SavedState(superState);
			ss.mMax = mMax;
			ss.mProgress = mProgress;
			return ss;
		}
		return superState;
	}

	@Override
	public void onRestoreInstanceState(Parcelable state) {
		if (!(state instanceof SavedState)) {
			super.onRestoreInstanceState(state);
			return;
		}

		SavedState ss = (SavedState) state;
		super.onRestoreInstanceState(ss.getSuperState());

		mMax = ss.mMax;
		mProgress = ss.mProgress;
	}
}
